<?php

declare(strict_types=1);
/**
 * This file is part of Hyperf.
 *
 * @link     https://www.hyperf.io
 * @document https://hyperf.wiki
 * @contact  group@hyperf.io
 * @license  https://github.com/hyperf/hyperf/blob/master/LICENSE
 */
namespace App\Room;

use App\Player\Player;

class Room
{
    protected $max_player;

    protected $type;

    protected $players = [];

    protected $visiters = [];

    protected $ghost = [];

    protected $playerTimer = []; // user_id => timerid

    private $id;

    private $isStart = false;

    private $day = 1;

    private $isNight = false;

    public function __construct($id, $max_player, $type)
    {
        $this->id = $id;
        $this->max_player = $max_player;
        $this->type = $type;
    }

    public function __destruct()
    {
        // TODO: Implement __destruct() method.
    }

    public function setPlayer($userId)
    {
        if (count($this->players) >= $this->max_player) {
            throw new \Exception('Too Much Player', 1);
        }
        $this->players[$userId] = new Player($userId, 'player', $this->id, $this->getAvailablePlaceNum());
    }

    public function removePlayer($userId)
    {
        unset($this->players[$userId]);
    }

    public function setVisiter($userId)
    {
        $this->visiters[$userId] = new Player($userId, 'visiter', $this->id, 0);
    }

    public function removeVisiter($userId)
    {
        unset($this->visiters[$userId]);
    }

    public function getPlayers()
    {
        return array_keys($this->players);
    }

    public function getVisiters()
    {
        return array_keys($this->visiters);
    }

    public function setGhost($userId)
    {
        // 只有 player 能成为 ghost
        if (! isset($this->players[$userId])) {
            return;
        }
        $this->ghost[$userId] = new Player($userId, $this->id, 'ghost');
    }

    public function getGhosts()
    {
        return array_keys($this->ghost);
    }

    public function playerChangeplace($userId, $newPlaceNum)
    {
        $usedPlaces = $this->getUsedPlaceNums();
        if (in_array($newPlaceNum, $usedPlaces)) {
            throw new \Exception('座位已被占用');
        }
        $player = $this->getPlayerById($userId);
        $player->setPlaceNum($newPlaceNum);
        $this->players[$userId] = $player;
    }

    public function playerSpeak($userId)
    {
        $player = $this->getPlayerById($userId);
        $timerId = $player->speak();
        $this->playerTimer[$userId] = $timerId;
    }

    public function playerSpeakOver($userId)
    {
        $player = $this->getPlayerById($userId);
        $player->speakOver();
        unset($this->playerTimer[$userId]);
    }

    public function visiterSpeak()
    {
    }

    public function visiterSpeakOver()
    {
    }

    public function ghosterSpeak()
    {
    }

    public function ghostSpeakOver()
    {
    }

    public function startGame()
    {
        $this->isStart = true;
    }

    public function finishGame()
    {
        $this->isStart = false;
    }

    public function kill($userId, $killUserId)
    {
        $killer = $this->getPlayerById($userId);
        if (! $this->canKill($killer->getGameRole())) {
            throw new \Exception('当前身份不能杀人');
        }
        $victim = $this->getPlayerById($killUserId);
        // User role in game will be number and enum, string only show in fake code !
        if ($killer->getGameRole() == 'werewolf') {
            if (! $this->isNight) {
                throw new \Exception('白天狼不能嚣张杀人');
            }
            $victim->killByWerewolf();
        }
        if ($killer->getGameRole() == 'witch') {
            if (! $this->isNight) {
                throw new \Exception('白天女巫不能泼毒');
            }
            $victim->killByWitch();
        }
        if ($killer->getGameRole() == 'hunte') {
            if ($this->isNight) {
                throw new \Exception('晚上猎人不能开枪');
            }
            $victim->killByHunte();
        }
        $this->updatePlayer($killUserId, $victim);
    }

    public function incrDay()
    {
        $this->day++;
    }

    public function inNight()
    {
        $this->isNight = true;
    }

    public function inSun()
    {
        $this->isNight = false;
    }

    public function distributionRole()
    {
        $allRoles = $this->getAllRoles();
        $shuffRoles = shuffle($allRoles);
        foreach ($this->players as $userId => $player) {
            /** @var Player $player */
            $player->setGameRole(end($shuffRoles));
            $this->updatePlayer($userId, $player);
        }
    }

    protected function getAllRoles()
    {
        return [];
    }

    protected function getAvailablePlaceNum()
    {
        $usedPlaces = $this->getUsedPlaceNums();
        $allPlaces = range(1, $this->max_player);
        $availablePlaces = array_diff($allPlaces, $usedPlaces);
        return $availablePlaces[0];
    }

    protected function getUsedPlaceNums()
    {
        $usedPlaces = [];
        foreach ($this->players as $player) {
            /* @var Player $player */
            array_push($usedPlaces, $player->getPlaceNum());
        }
        return $usedPlaces;
    }

    protected function getPlayerById($userId): Player
    {
        if (! isset($this->players[$userId])) {
            throw new \Exception('用户不存在于此房间');
        }
        return $this->players[$userId];
    }

    protected function canKill($role)
    {
        return true;
    }

    protected function updatePlayer($userId, Player $player)
    {
        $this->players[$userId] = $player;
    }
}
